﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Reflection;
using System.Windows.Forms;


namespace Marmat.Forms
{
    [ProvideProperty("ColName", typeof(Control))]
    [ProvideProperty("DataType", typeof(Control))]
    [ProvideProperty("AllowClear", typeof(Control))]
    [ProvideProperty("Compare", typeof(Control))]
    [ProvideProperty("PropertyName", typeof(Control))]
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(FilterPanel), "FilterControl.png")]
    [Designer(" Marmat.Forms.BFilterPanelDesigner")]
    public class FilterPanel : System.Windows.Forms.UserControl, IExtenderProvider, IControl
    {
        private Hashtable _ColNameTable = new Hashtable();
        private Hashtable _DataTypeTable = new Hashtable();
        private Hashtable _CompareTable = new Hashtable();
        private Hashtable _PropertyNameTable = new Hashtable();
        private Hashtable _AllowClear = new Hashtable();

        public FilterPanel()
        {

            // 此调用是设计器所必需的。
            this.InitializeComponent();
            this.SetStyle(ControlStyles.ContainerControl, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            // 在 InitializeComponent() 调用之后添加任何初始化。

        }

        [DefaultValue(null)]
        [Category("数据")]
        [DisplayName("Table")]
        [Description("筛选控件绑定的表。")]
        public DataGrid Table { get; set; }

        [DefaultValue("'")]
        [Category("数据")]
        [DisplayName("DatePrefix")]
        [Description("日期格式筛选的时候加的格式符。")]
        public string DatePrefix { get; set; } = "'";

        /// <summary>
        /// 读取控件的筛选属性时发生,通常用来根据控件的值，指定成不同的筛选值进行筛选。
        /// </summary>
        /// <remarks></remarks>
        [Description("读取控件的筛选属性时发生,通常用来根据控件的值，指定成不同的筛选值进行筛选。")]
        public event GetPropertyValuingEventHandler GetPropertyValuing;

        public delegate void GetPropertyValuingEventHandler(object sender, PropertyValueEventArgs e);

        /// <summary>
        /// 设置控件的筛选属性时发生，通常用于在清除时指定控件的默认值。
        /// </summary>
        /// <remarks></remarks>
        [Description("设置控件的筛选属性时发生，通常用于在清除时指定控件的默认值。")]
        public event SetPropertyValuingEventHandler SetPropertyValuing;

        public delegate void SetPropertyValuingEventHandler(object sender, PropertyValueEventArgs e);

        // <DefaultValue(CStr(Nothing)), Category("数据"), DisplayName("FindButton"), Description("自动触发筛选的按钮控件。")>
        // Public Property FindButton As Button
        // Get
        // Return m_FindButton
        // End Get
        // Set(value As Button)
        // m_FindButton = value
        // End Set
        // End Property
        // Private WithEvents m_FindButton As Button

        // <DefaultValue(CStr(Nothing)), Category("数据"), DisplayName("ClearButton"), Description("自动触发清除的按钮控件。")>
        // Public Property ClearButton As Button
        // Get
        // Return m_ClearButton
        // End Get
        // Set(value As Button)
        // m_ClearButton = value
        // End Set
        // End Property
        // Private WithEvents m_ClearButton As Button

        [Browsable(true)]
        [DefaultValue(null)]
        [Category("筛选属性")]
        [DisplayName("ColName")]
        [Description("对应的数据列名。")]
        public string GetColName(Control control)
        {
            string Value = Convert.ToString(this._ColNameTable[control]);
            return Value;
        }

        public void SetColName(Control control, string value)
        {
            if (!string.IsNullOrEmpty(value)) // 要保存配置
            {
                if (this._ColNameTable.Contains(control) == false)
                {
                    this._ColNameTable.Add(control, value);
                }
                else
                {
                    this._ColNameTable[control] = value;
                }
            }
            else
            {
                this._ColNameTable.Remove(control);
            }
        }

        [Browsable(true)]
        [DefaultValue(true)]
        [Category("筛选属性")]
        [DisplayName("AllowClear")]
        [Description("是否参与清除方法。")]
        public bool GetAllowClear(Control control)
        {
            bool Value = true;
            if (this._AllowClear.ContainsKey(control))
            {
                Value = Convert.ToBoolean(this._AllowClear[control]);
            }

            return Value;
        }

        public void SetAllowClear(Control control, bool value)
        {
            // If value <> Nothing Then '要保存配置
            if (this._AllowClear.Contains(control) == false)
            {
                this._AllowClear.Add(control, value);
            }
            else
            {
                this._AllowClear[control] = value;
            }
            // Else
            // Me._AllowClear.Remove(control)
            // End If
        }

        [Browsable(true)]
        [TypeConverter(typeof(DataTypeConverter))]
        [DefaultValue(typeof(string))]
        [Category("筛选属性")]
        [DisplayName("DataType")]
        [Description("对应的数据类型。")]
        public Type GetDataType(Control control)
        {
            Type Value = (Type)this._DataTypeTable[control];
            if (Value is null)
            {
                return typeof(string);
            }

            return Value;
        }

        public void SetDataType(Control control, Type value)
        {
            if (value is object) // 要保存配置
            {
                if (this._DataTypeTable.Contains(control) == false)
                {
                    this._DataTypeTable.Add(control, value);
                }
                else
                {
                    this._DataTypeTable[control] = value;
                }
            }
            else
            {
                this._DataTypeTable.Remove(control);
            }
        }

        [Browsable(true)]
        [DefaultValue(typeof(Compare), "等于")]
        [Category("筛选属性")]
        [DisplayName("Compare")]
        [Description("对应的逻辑运算符。")]
        public Compare GetCompare(Control control)
        {
            Compare Value = (Compare)this._CompareTable[control];
            if ((int)Value <= 0)
            {
                Value = Compare.等于;
            }

            return Value;
        }

        public void SetCompare(Control control, Compare value)
        {
            if ((int)value > 0) // 要保存配置
            {
                if (this._CompareTable.Contains(control) == false)
                {
                    this._CompareTable.Add(control, value);
                }
                else
                {
                    this._CompareTable[control] = value;
                }
            }
            else
            {
                this._CompareTable.Remove(control);
            }
        }

        [Browsable(true)]
        [DefaultValue(null)]
        [Category("筛选属性")]
        [DisplayName("PropertyName")]
        [Description("筛选时访问控件的属性名。")]
        public string GetPropertyName(Control control)
        {
            if (this._PropertyNameTable.Contains(control) == false)
            {
                foreach (string PropertyName in new[] { "Value", "Checked", "Text" })
                {
                    foreach (PropertyInfo Item in control.GetType().GetProperties())
                    {
                        if ((Item.Name ?? "") == (PropertyName ?? ""))
                        {
                            return Item.Name;
                        }
                    }
                }
            }

            string Value = Convert.ToString(this._PropertyNameTable[control]);
            return Value;
        }

        public void SetPropertyName(Control control, string value)
        {
            if (!string.IsNullOrEmpty(value)) // 要保存配置
            {
                if (this._PropertyNameTable.Contains(control) == false)
                {
                    this._PropertyNameTable.Add(control, value);
                }
                else
                {
                    this._PropertyNameTable[control] = value;
                }
            }
            else
            {
                this._PropertyNameTable.Remove(control);
            }
        }

        /// <summary>
        /// 获取筛选控件组合的Filter值
        /// </summary>
        /// <returns></returns>
        /// <remarks></remarks>
        public string GetString()
        {
            var txt = new System.Text.StringBuilder();
            foreach (Control item in this._PropertyNameTable.Keys)
            {
                string ColName = this.GetColName(item);
                var DataType = this.GetDataType(item);
                var Compare = this.GetCompare(item);
                string CompareStr = this.GetOperatorString(Compare);
                string PropertyName = this.GetPropertyName(item);
                if (!string.IsNullOrEmpty(PropertyName) && !string.IsNullOrEmpty(ColName) && !string.IsNullOrEmpty(CompareStr) && DataType is object)
                {
                    var Propertys = item.GetType().GetProperties();
                    foreach (PropertyInfo Info in Propertys)
                    {
                        if ((Info.Name ?? "") == (PropertyName ?? ""))
                        {
                            var EventArg = new PropertyValueEventArgs();
                            EventArg.Control = item;
                            EventArg.Value = Info.GetValue(item, null);
                            GetPropertyValuing?.Invoke(this, EventArg);
                            if (EventArg.Cancel == false && EventArg.Value is object)
                            {
                                var ItemValue = EventArg.Value;
                                switch (DataType)
                                {
                                    case var @case when @case == typeof(string):
                                        {
                                            string value = ItemValue.ToString();
                                            if (!string.IsNullOrEmpty(value))
                                            {
                                                if (txt.Length > 0)
                                                    txt.Append(" And ");
                                                if (CompareStr == "Like")
                                                {
                                                    txt.Append($"[{ColName}] {CompareStr} '%{value.Replace("'", "''")}%'");
                                                }
                                                else if (CompareStr == "IN")
                                                {
                                                    txt.Append($"[{ColName}] {CompareStr}('{value.Replace("'", "''").Replace(",", "','")}')");
                                                }
                                                else if (CompareStr == "NOT IN")
                                                {
                                                    txt.Append($"[{ColName}] {CompareStr}('{value.Replace("'", "''").Replace(",", "','")}')");
                                                }
                                                else
                                                {
                                                    txt.Append($"[{ColName}] {CompareStr} '{value.Replace("'", "''")}'");
                                                }
                                            }
                                            break;
                                        }

                                    case var case1 when case1 == typeof(DateTime):
                                        {
                                            if (Convert.ToDateTime(ItemValue) != default)
                                            {
                                                if (txt.Length > 0)
                                                    txt.Append(" And ");
                                                switch (Compare)
                                                {
                                                    case Forms.Compare.大于:
                                                    case Forms.Compare.大于等于:
                                                        {
                                                            ItemValue = Convert.ToDateTime(ItemValue).Date + " 00:00:00";
                                                            break;
                                                        }

                                                    case Forms.Compare.小于:
                                                    case Forms.Compare.小于等于:
                                                        {
                                                            ItemValue = Convert.ToDateTime(ItemValue).Date + " 23:59:59";
                                                            break;
                                                        }

                                                    case Forms.Compare.等于:
                                                        {
                                                            txt.Append("([" + ColName + "] >=" + this.DatePrefix + ItemValue + " 00:00:00" + this.DatePrefix + " AND [" + ColName + "] <=" + this.DatePrefix + ItemValue + " 23:59:59" + this.DatePrefix + ")");
                                                            break;
                                                        }
                                                }
                                                txt.Append("[" + ColName + "] " + CompareStr + " " + this.DatePrefix + ItemValue + this.DatePrefix);
                                            }

                                            break;
                                        }

                                    case var case2 when case2 == typeof(decimal):
                                    case var case3 when case3 == typeof(double):
                                    case var case4 when case4 == typeof(float):
                                    case var case5 when case5 == typeof(short):
                                    case var case6 when case6 == typeof(byte):
                                    case var case7 when case7 == typeof(int):
                                        {
                                            if (ItemValue is object && Convert.ToDecimal(ItemValue) != default)
                                            {
                                                if (txt.Length > 0)
                                                {
                                                    txt.Append(" And ");
                                                }
                                                txt.Append("[" + ColName + "] " + CompareStr + ItemValue);
                                            }

                                            break;
                                        }

                                    case var case8 when case8 == typeof(bool):
                                        {
                                            if (ItemValue is object && txt.Length > 0)
                                            {
                                                txt.Append(" And ");
                                            }
                                            txt.Append("[" + ColName + "] " + CompareStr + " " + (ItemValue is true ? 1 : 0));
                                            break;
                                        }
                                }
                            }

                            break;
                        }
                    }
                }
            }

            return txt.ToString();
        }

        /// <summary>
        /// 清除参与筛选控件中的值。
        /// </summary>
        /// <remarks></remarks>
        public void ClearValue()
        {
            foreach (Control item in this._PropertyNameTable.Keys)
            {
                if (!string.IsNullOrEmpty(this.GetPropertyName(item)) && !string.IsNullOrEmpty(this.GetColName(item)) && this.GetCompare(item) != default(int) && this.GetDataType(item) is object)
                {
                    if (this.GetAllowClear(item) == true)
                    {
                        var DataType = this.GetDataType(item);
                        string PropertyName = this.GetPropertyName(item);
                        var Propertys = item.GetType().GetProperties();
                        foreach (PropertyInfo Info in Propertys)
                        {
                            if ((Info.Name ?? "") == (PropertyName ?? "") && Info.GetValue(item, null) is object)
                            {
                                var EventArg = new PropertyValueEventArgs();
                                EventArg.Control = item;
                                EventArg.Value = null;
                                SetPropertyValuing?.Invoke(this, EventArg);
                                if (!EventArg.Cancel) // AndAlso DataType Is EventArg.Value Then
                                {
                                    Info.SetValue(item, EventArg.Value, null);
                                }

                                break;
                            }
                        }
                    }
                }
            }
        }

        private string GetOperatorString(Compare Compare)
        {
            switch (Compare)
            {
                case Compare.不等于:
                    {
                        return "<>";
                    }

                case Compare.大于:
                    {
                        return ">";
                    }

                case Compare.大于等于:
                    {
                        return ">=";
                    }

                case Compare.等于:
                    {
                        return "=";
                    }

                case Compare.小于:
                    {
                        return "<";
                    }

                case Compare.小于等于:
                    {
                        return "<=";
                    }

                case Compare.包含:
                    {
                        return "Like";
                    }

                case Compare.多值等于:
                    {
                        return "IN";
                    }

                case Compare.多值不等于:
                    {
                        return "NOT IN";
                    }

                case Compare.首部匹配:
                    {
                        return "Like";
                    }

                case Compare.尾部匹配:
                    {
                        return "Like";
                    }
            }

            return "=";
        }

        // Protected Overrides Sub OnPaint(e As PaintEventArgs)
        // Using Pen As New Pen(Color.FromArgb(100, 83, 83, 83))
        // Pen.DashStyle = Drawing2D.DashStyle.Dash
        // e.Graphics.DrawRectangle(Pen, New Rectangle(0, 0, Me.Width - 1, Me.Height - 1))
        // End Using
        // MyBase.OnPaint(e)
        // End Sub

        // Private Sub m_FindButton_Click(sender As Object, e As EventArgs) Handles m_FindButton.Click
        // If Me.Table IsNot Nothing Then
        // Me.Table.Load(Me.GetString)
        // End If
        // End Sub

        // Private Sub m_ClearButton_Click(sender As Object, e As EventArgs) Handles m_ClearButton.Click
        // If Me.Table IsNot Nothing Then
        // Me.ClearValue()
        // Me.Table.Load(Me.GetString)
        // End If
        // End Sub

        /* TODO ERROR: Skipped RegionDirectiveTrivia */
        bool IExtenderProvider.CanExtend(object extendee)
        {
            // TODO: 添加 Component1.CanExtend 实现
            if (extendee is Control && !(extendee is FilterPanel))
            {
                return this.FindCanExtend((Control)extendee);
            }
            else
            {
                return false;
            }
        }

        protected internal bool FindCanExtend(Control Control)
        {
            var Parent = Control.Parent;
            if (Parent is object)
            {
                if (ReferenceEquals(Parent, this))
                {
                    return true;
                }
                else
                {
                    return this.FindCanExtend(Parent);
                }
            }

            return false;
        }
        /* TODO ERROR: Skipped EndRegionDirectiveTrivia */
        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // FilterPanel
            // 
            this.Name = "FilterPanel";
            this.Size = new Size(500, 72);
            this.ResumeLayout(false);
        }
    }

    public enum Compare
    {
        小于 = 1,
        大于 = 2,
        小于等于 = 4,
        大于等于 = 8,
        不等于 = 16,
        等于 = 32,
        多值等于 = 64,
        多值不等于 = 128,
        包含 = 256,
        首部匹配 = 512,
        尾部匹配 = 1024
    }
}